package cn.example.freid.util;


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * singleton utility used for transform resultSet to list.
 * @author Freid
 */
public class ResultsetUtil {

	
	/**
	 * transform resultSet to arrayList
	 * @param rs resultSet that need to transformed
	 * @param clazz object class that contained in list
	 * @return
	 * @throws SQLException
	 */
	public static <T> List<T> resultsetToList(ResultSet rs, Class<T> clazz) throws SQLException {
		
		//get all methods contained in target class
		Method[] methods = clazz.getDeclaredMethods();
		List<T> returnList = new ArrayList<T>();
		//element in list
		T obj;
		
		//get metaData to go over all columns
		ResultSetMetaData rsmd = rs.getMetaData();
		String colName;
		String methodName;
		
		//System.out.println("================Result Set Tranform begin=================");
		
		while(rs.next()) {
			
			try {
				
				//Equals obj = new Object()
				obj = clazz.newInstance();
			} catch (InstantiationException e2) {

				e2.printStackTrace();
				return null;
			} catch (IllegalAccessException e2) {
				
				e2.printStackTrace();
				return null;
			}
			
			//System.out.println("------Current row :"+rs.getRow()+",colums ergodic begin-----");
			
			//for every column, get column name, spell it for set method name, then invoke the method.
			for (int curCol = 1; curCol<= rsmd.getColumnCount(); curCol++) {
				
				colName = rsmd.getColumnName(curCol);
				colName = colName.replaceAll("_", "");
				methodName = "set"+colName;
				
				//System.out.println("Current column name :"+colName);
				//System.out.println("Current method name :"+methodName);
				
				for (Method method : methods) {
					if (method.getName().equalsIgnoreCase(methodName)) {
						
						methodName = method.getName();
						Object value = rs.getObject(curCol);
						//System.out.println("Current column value :"+value);
						
						if (value == null)
							continue;
						
						try {
							
							Method classMethod;
							if (value.getClass().equals(BigDecimal.class)) {
								
								classMethod = obj.getClass().getDeclaredMethod(methodName, double.class);
								value = new Double(((BigDecimal)value).doubleValue());
							} else {
								
								classMethod = obj.getClass().getDeclaredMethod(methodName, value.getClass());
							}
							classMethod.invoke(obj, value);
							
						} catch (NoSuchMethodException e) {
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							e.printStackTrace();
						} catch (IllegalArgumentException e) {
							e.printStackTrace();
						} catch (InvocationTargetException e) {
							e.printStackTrace();
						} catch (SecurityException e) {
							e.printStackTrace();
						}
						
					}
				}
				
			}
			
			//System.out.println("------row "+rs.getRow()+" ergodic finished-----");
			//System.out.println();
			
			returnList.add(obj);	
		}
		
		//System.out.println("================Result Set Tranform finished=================");
 		
		return returnList;
	}
	
	public static String resultsetToJson(ResultSet rs) throws SQLException {
		
	   JSONArray array = new JSONArray();  
	    
	   ResultSetMetaData metaData = rs.getMetaData();  
	   int columnCount = metaData.getColumnCount();  
	    
	    while (rs.next()) {  
	        JSONObject jsonObj = new JSONObject();  

	        for (int i = 1; i <= columnCount; i++) {  
	            String columnName =metaData.getColumnLabel(i);  
	            String value = rs.getString(columnName);  
	            jsonObj.put(columnName, value.trim());  
	        }   
	        array.add(jsonObj);
	    }  
	    
	   return array.toString();  
	}

}
